/*
 * Asteroide.cpp
 *
 *  Created on: Apr 5, 2012
 *      Author: gonzalo-Ramiro
 */

#include "Asteroide.h"
#include "../common/lib/SDL_rotozoom.h"
#include "../common/utils/SurfaceUtils.h"
#include "widgets/PlayScenarioPanel.h"
#include "widgets/Explosion.h"

#define MAX_ASTEROIDE_CHILD 3
#define ASTEROIDE_DIF_AL_CHOQUE 45

Asteroide::Asteroide(DTOAsteroide* dto) :
WidgetMovimiento(ASTEROID,dto->x, dto->y, dto->tipo->ancho / dto->nivel,
		dto->tipo->alto / dto->nivel,dto->tipo->imagePath,NULL) {

	this->Id = dto->Id;
	this->angle = dto->tipo->rotacion;
	this->direccion = dto->direccion;
	this->velocity = dto->velocidad;
	this->tipo = new TipoAsteroide(dto->tipo);
	this->nivel = dto->nivel;
}


DTOAsteroide* Asteroide::getDTO(std::string owner) {
	SDL_Rect rectangle = parcel->getRectangle();
	return new DTOAsteroide(Id, nivel, tipo->getDTO(),rectangle.x,rectangle.y,direccion,velocity, drawable,owner);
}

void Asteroide::setParent(Widget* widget){
	//TODO posible memory leak
	this->parent = widget;
}

void Asteroide::handleEvent(Event event) {
	if(event.getEvent()->user.code == Asteroid_Status){
		std::string data = event.getData();
		DTOAsteroide* asteroide = new DTOAsteroide(data, std::string(SERVER_OWN));
		if (!asteroide->getDrawable()){
			if (asteroide->Id == Id){
				drawable = false;
			}
		}
		delete asteroide;
	}
}

void Asteroide::handleColision(WidgetMovimiento* with){

	if (((PlayScenarioPanel*)parent)->isAdmin()){
		if( with->getType() == SHIP || with->getType() == AMMO ){
			PlayScenarioPanel* playScenario = ((PlayScenarioPanel*)parent);

			drawable = false;
			// Mensaje de destruccion del asteroide
			playScenario->getInterface()->setDTOMensaje(getDTO(playScenario->getOwner()));

			SDL_Rect rectangle = parcel->getRectangle();
			playScenario->add(new Explosion(rectangle.x,rectangle.y,parent));
			// Mensaje de creacion de la explosion
			playScenario->getInterface()->setDTOMensaje(new DTOExplosion(rectangle.x,rectangle.y,playScenario->getOwner()));

			if(nivel < MAX_ASTEROIDE_CHILD){
				Asteroide* newAsteroide1 = getChild(playScenario->getUltimoIdAsteroide(),with->getAngle() - ASTEROIDE_DIF_AL_CHOQUE);
				playScenario->add(newAsteroide1);
				// Mensaje de creacion del asteroide
				playScenario->getInterface()->setDTOMensaje(newAsteroide1->getDTO(playScenario->getOwner()));

				Asteroide* newAsteroide2 = getChild(playScenario->getUltimoIdAsteroide(),with->getAngle() + ASTEROIDE_DIF_AL_CHOQUE);
				playScenario->add(newAsteroide2);
				// Mensaje de creacion del asteroide
				playScenario->getInterface()->setDTOMensaje(newAsteroide2->getDTO(playScenario->getOwner()));
			}else{
				Bonus* newBonus = BonusGenerator::generateBonus(this,parent);
				if(newBonus){
					playScenario->add(newBonus);
					playScenario->getInterface()->setDTOMensaje(newBonus->getDTO(playScenario->getOwner()));
				}
			}
		}
	}
}

void Asteroide::resolve() {
	if(!timer.is_started()){
		timer.start();
	}

	float secsPerFrame = (timer.get_ticks() / 1000.0);

	parcel->updateXY(nextX,nextY);

	int posX0 = nextX;
	int posY0 = nextY;

	float angleInRadians = direccion * (M_PI / 180);

	float velX = velocity * cos(angleInRadians);
	float velY = (-1.0) * velocity * sin(angleInRadians);

	float deltaX = fabs(velX * secsPerFrame);
	deltaX = floor(deltaX * 100) / 100;
	deltaX = floor(deltaX + 0.5);
	float deltaY = fabs(velY * secsPerFrame);
	deltaY = floor(deltaY * 100) / 100;
	deltaY = floor(deltaY + 0.5);

	if(velX >= 0)
		nextX = posX0 + deltaX;
	else if(velX < 0)
		nextX = posX0 - deltaX;

	if (velY >= 0)
		nextY = posY0 + deltaY;
	else if (velY < 0)
		nextY = posY0 - deltaY;

	WidgetMovimiento::resolve();

	timer.start();
}

Asteroide::~Asteroide() {
	timer.stop();
	delete tipo;
}


Asteroide* Asteroide::getChild(int id,int direccion){
	//if i get childs is because it died
	this->drawable = false;

	DTOAsteroide* dtoAsteroide = getDTO();
	//Mark it as a slim version, save bandwith
	dtoAsteroide->slimDTOVersion = true;
	dtoAsteroide->Id = id;
	dtoAsteroide->nivel++;
	dtoAsteroide->direccion = direccion;
	dtoAsteroide->velocidad = dtoAsteroide->velocidad/2;

	if(dtoAsteroide->tipo->ancho / dtoAsteroide->nivel <= 1){
		dtoAsteroide->tipo->ancho += dtoAsteroide->nivel;
	}else{
		if(dtoAsteroide->tipo->alto / dtoAsteroide->nivel <= 1){
			dtoAsteroide->tipo->alto += dtoAsteroide->nivel;
		}
	}

	Asteroide* returno = new Asteroide(dtoAsteroide);
	returno->setParent(this->parent);

	delete dtoAsteroide;

	return returno;
}


int Asteroide::getId() {
	return Id;
}

TipoAsteroide* Asteroide::getTipo(){
	return tipo;
}

int Asteroide::getX(){
	return this->nextX;
}

int Asteroide::getY(){
	return this->nextY;
}

int Asteroide::getDireccion(){
	return this->direccion;
}

int Asteroide::getVelocidad(){
	return this->velocity;
}

int Asteroide::getNivel(){
	return this->nivel;
}
